package org.nf.web.servlet.mapping;

import jakarta.servlet.http.HttpServletRequest;
import org.nf.web.servlet.Controller;
import org.nf.web.servlet.FrameworkContext;
import org.nf.web.servlet.HandlerExecutionChain;
import org.nf.web.servlet.annotation.RequestMapping;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * @author wangliang
 * @date 2023/4/19
 * 根据请求url找到对应的Controller对象
 */
public class SimpleControllerHandlerMapping extends AbstractHandlerMapping {

    private final Map<String, Class<?>> controllerMap = new HashMap<>();

    public SimpleControllerHandlerMapping() {
        //循环遍历集合并加载Class对象
        FrameworkContext.getInstance().getClasses().forEach(handler -> {
            if(Controller.class.isAssignableFrom(handler)) {
                if(handler.isAnnotationPresent(RequestMapping.class)) {
                    String uri = handler.getAnnotation(RequestMapping.class).value();
                    //如果存在HandlerMethodMap中存在此uri，则抛出异常
                    if(controllerMap.containsKey(uri)) {
                        throw new RuntimeException("This uri already exists：" + uri);
                    }
                    controllerMap.put(uri, handler);
                }
            }
        });
    }

    @Override
    public HandlerExecutionChain getHandler(HttpServletRequest request) {
        //查找映射前去掉uri的contextPath名称
        String uri = getRequestURI(request);
        //查找相应的控制器
        Object handler = controllerMap.get(uri);
        if(handler == null) {
            if(lfuCache.containsKey(uri)) {
                handler = controllerMap.get(lfuCache.get(uri));
            } else {
                Optional<String> optional = controllerMap.keySet().stream()
                        .filter(path -> pathMatcher.match(path, uri)).findAny();
                if(optional.isPresent()) {
                    handler = controllerMap.get(optional.get());
                    //缓存uri映射
                    lfuCache.put(uri, optional.get());
                }
            }

        }
        //返回拦截器链
        return getHandlerExecutionChain(request, handler);
    }
}
